function LuckyNumber() {
    this.users = {                  // 参加本次抽奖活动的玩家信息 
        /*
        uid : {
            name : '',
            number : 0,         
        }
        */
    };
    
    this.luckyNumber = -1;          // 每期开奖幸运号码[0-999]
    this.openDay = 0;               // 本期幸运号码开奖日期
    // 内存变量
    this.selectNumbers = {          // 本期号码选择分布情况
        /*number : count*/
    };
    
    this.wins = [                   // 中奖记录
        /*{uid:name}*/              // 玩家UID:玩家姓名
    ];
}

LuckyNumber.create = function() {

    var cloudShop = {
        _id: 'cloud_shop', 
        ai : 1,
        shop_list: {        // 销售列表
            /*
            id : {          // cloudshop ID
                index:      // 循环ID
                times:      // 期号20131120 12345
                id :        // cloud ID
                time :      // 结束时间
                sold :      // 卖出量
                users: {
                    uid : {
                        seqs : []   // 玩家购买序号
                        name : ''   // 玩家名字
                        headpic:''  // 玩家头像
                    }
                }
            }
            */
        },

        wins : {            // 中奖纪录
            /*
            times : {       // 期号
                sid:        // 云购shopId
                id:         // 云购id
                name:       // 获奖者名字
                headpic:    // 获奖者头像
                uid :       // 中奖玩家
                code :      // 购票序号 times + seq
                reward:     // 是否领奖
                time:       // 开奖时间
            }
            */
        },

        time_ends : {       // 时限类结束标志
            /*
                id : day
            */
        },

        last_wins : [],     // 最近获奖记录
        buys : {},          // 玩家历史购买次数
    };

    gDBWorld.insert(cloudShop, function(err, result){});
};

LuckyNumber.prototype = {
    init : function(callback) {
        gDBWorld.findOne({_id : 'cloud_shop'}, {}, function(err, doc){
            if( doc ) {
                this.shopList = doc.shop_list;
                this.wins = doc.wins;
                this.buys = doc.buys;
                this.ai = doc.ai;
                this.lastWins = doc.last_wins;
                this.timeEnds = doc.time_ends || {};

                this._init(callback);
            }else{
                callback && callback(false);
            }
        }.bind(this));
    },

    _init : function(callback) {
        for( var id in this.wins ) {
            this.updateLastWin(this.wins[id].sid, this.wins[id]);
        }
        callback && callback(true);
    },

    save : function(callback) {
        this.checkWins();

        var cloudShop = {
            _id: 'cloud_shop', 
            ai : this.ai,
            shop_list: this.shopList,
            wins : this.wins,
            buys : this.buys,
            last_wins : this.lastWins,
            time_ends : this.timeEnds,
        };
        gDBWorld.save(cloudShop, function(err, result){
            if( err ) {
                ERROR(util.format('SAVE CLOUD_SHOP: %j %j', err, cloudShop));
                callback && callback(false);
            }else {
                callback && callback(true);
            }
        });
    },

    checkWins : function() {
        // 删除1天以前的领取过奖的
        var checkedWins = {};
        var timeStamp = common.getTime() - 86400;
        for( var times in this.wins ) {
            var win = this.wins[times];
            if( !win.reward || win.time > timeStamp ) {
                checkedWins[times] = win;
            }
        }

        this.wins = checkedWins;
    },

    updateLastWin : function(id, win) {
        if( !this.lastWin[id] || win.time > this.lastWin[id].time) {
            this.lastWin[id] = win;
        }
    },

    addBuy : function(uid, count) {
        if( !this.buys[uid] ) {
            this.buys[uid] = count;
        }else{
            this.buys[uid] += count;
        }
    },

    getCloudLevel : function(uid) {
        var buy = this.buys[uid] || 0;
        var i = 1;
        for( i=1; i<1000; i++ ) {
            if( !gConfCloudLevel[i+1] || gConfCloudLevel[i].Buy >= buy ) {
                break;
            }
        }

        return i;
    },

    updateShopList : function() {
        for( var id in gConfCloudShop ) {
            var conf = gConfCloudShop[id];
            if( conf.CloudType == 1 ) {
                // 人气
                if( !this.shopList[id] ) {
                    // 没有
                    this.updateShopList1(id);
                }
            }else if( conf.CloudType == 2 ) {
                // 限时
                if( !this.shopList[id] ) {
                    this.updateShopList2(id);
                }else{
                    this.openWin(id);
                }
            }
        }
    },

    openWin : function(id) {
        var conf = gConfCloudShop[id];
        var shopList = this.shopList[id];
        var now = common.getTime();
        if( (conf.CloudType == 2) && shopList.time > now ) {
            return false;
        }

        if( (conf.CloudType == 1) && shopList.sold * gConfGlobal.CloudUnitPrice < gConfCloud[shopList.id].Price ) {
            return false;
        }
        
        var haveBought = false;
        var weights = {};
        var shopList = this.shopList[id];
        var userBuy = shopList.users;
        for( var uid in userBuy ) {
            var addRate = gConfCloudLevel[this.getCloudLevel(uid)].AddRate;

            weights[uid] = userBuy[uid].seqs.length * (100+addRate);
            haveBought = true;
        }
        
        if( haveBought ) {
            var winner = +common.wRand(weights);
            var winnerName = shopList.users[winner].name;
            var winnerHeadpic = shopList.users[winner].headpic;
            var strSeq = ('00000' + common.randArray(shopList.users[winner].seqs)).substr(-5, 5);
            this.wins[shopList.times] = {
                sid : id,
                id: shopList.id,
                uid : winner,
                name : winnerName,
                headpic : winnerHeadpic,
                code : shopList.times + strSeq,
                reward: 0,
                time: now,
            };
            this.updateLastWin(id, this.wins[shopList.times]);

            delete this.buyLogs[shopList.times];
            this.lastWins.push([shopList.id, winner, winnerName]);
            if( this.lastWins.length >= 6 ) {
                this.lastWins = this.lastWins.slice(-6);
            }
        }

        if( conf.CloudType == 1 ) {
            this.updateShopList1(id);
        }else if( conf.CloudType == 2 ) {
            this.updateShopList2(id);
        }
    },

    updateShopList1 : function(id) {
        // 更新人气
        var shopList = this.shopList[id];
        var index = 0;
        if( shopList ) {
            index = shopList.index;
            index += 1;
        }

        var conf = gConfCloudShop[id];
        index = index % conf.Sell.length;
        
        var today = common.getDate();
        var times = this.getTimes();
        this.shopList[id] = {
            index:  index,
            times:  times,
            id :    conf.Sell[index],
            sold :  0,
            users:  {},
        };

        this.buyLogs[times] = [];
    },

    updateShopList2 : function(id) {
        // 更新时限
        var conf = gConfCloudShop[id];
        if( new Date().getHours() < gConfGlobal.CloudStartHour ) {
            // 每天有个开始时间
            return;
        }

        var today = common.getDate();
        if( this.timeEnds[id] == today ) {
            return;
        }

        var passedDay = common.getDayPassed(config.CloudShopTime);
        var lists = conf.Sell[passedDay%conf.Sell.length];

        var shopList = this.shopList[id];
        var index = 0;
        if( shopList && shopList.times.substr(0,8) == today ) {
            index = shopList.index + 1;
        }

        var newId = lists[index];
        if( !newId || (new Date().getHours() + conf.Time) >= 24 ) {
            // 今天结束,或者跨天了
            delete this.shopList[id];
            this.timeEnds[id] = today;
            return;
        }
        
        var times = this.getTimes();
        var endTime = common.getTime() + conf.Time * 3600;
        this.shopList[id] = {
            index:  index,
            time:   endTime,
            times:  times,
            id :    newId,
            sold :  0,
            users:  {},
        };

        this.buyLogs[times] = [];
    },

    getTimes : function(){
        // 获取期
        this.ai += 1;
        if( this.ai >= 100000 ) {
            this.ai = 1;
        }

        var today = common.getDate();

        return today + ('00000' + this.ai).substr(-5, 5);
    },

    getShopList : function() {
        var shopLists = {};
        for( var id in this.shopList ) {
            var shopList = this.shopList[id];
            var item = {};
            item.id = shopList.id;
            item.times = shopList.times;
            if( shopList.time ) {
                item.time = shopList.time;
            }
            
            item.sold = shopList.sold;
            shopLists[id] = item;
        }

        return shopLists;
    },

    buy : function(uid, id, num, name, headpic) {
        name = name || '';
        headpic = headpic || '';

        var shopList = this.shopList[id];
        if( !shopList ) {
            return false;
        }
        
        var maxBuy = gConfCloud[shopList.id].Price / gConfGlobal.CloudUnitPrice;
        if( (shopList.sold + num) > maxBuy ) {
            return false;
        }

        if( !shopList.users[uid] ) {
            shopList.users[uid] = {
                seqs : [],
                name : '',
                headpic : '',
            };
        }

        var userSeqs = shopList.users[uid].seqs;
        var maxPersonBuy = Math.floor(maxBuy * 0.05);
        if( (userSeqs.length + num) > maxPersonBuy ) {
            return false;
        }

        for( var i=1; i<=num; i++ ) {
            userSeqs.push(shopList.sold + i);
        }

        shopList.sold += num;
        shopList.users[uid].name = name;
        shopList.users[uid].headpic = headpic;
        this.buys[uid] = (this.buys[uid] || 0) + num;
        var logs = this.buyLogs[shopList.times];
        if( !logs ) {
            logs = [];
            this.buyLogs[shopList.times] = logs;
        }
        logs.push([uid, name, num, common.getTime()]);
        if( logs.length >= 5 ) {
            logs = logs.slice(-5);
        }
        
        var opened = 0;
        if( shopList.sold >= maxBuy && gConfCloudShop[id].CloudType == 1 ) {
            // 人气开奖
            this.openWin(id);
            opened = 1;
        }

        return {'times':shopList.times, 'seqs':userSeqs.slice(-num), 'opened':opened};
    },

    getReward : function(uid, times, name) {
        var win = this.wins[times];
        if( !win || win.uid != uid  || win.reward ) return false;
        
        win.reward = 1;

        return [gConfCloud[win.id].Award1];
    },
}

exports.get = function(req, res, resp) {
    var uid = req.uid;
    do {
        gCloudShop.updateShopList();

        resp.data.shop_list = gCloudShop.getShopList();
        resp.data.last_wins = gCloudShop.lastWins;
        resp.data.buy_count = gCloudShop.buys[uid] || 0;
    }while(false);
    
    onReqHandled(res, resp);
}

exports.get_cloud_detail = function(req, res, resp) {
    var uid = req.uid;
    do {
        gCloudShop.updateShopList();
        var shopList = gCloudShop.shopList[req.args.id];
        if( !shopList ) {
            resp.code = 1; resp.desc = 'invalid shop id'; break;
        }

        var wins = gCloudShop.wins;

        resp.data.last_win = gCloudShop.lastWin[req.args.id];
        resp.data.buy_log = gCloudShop.buyLogs[shopList.times] || [];
    }while(false);
    
    onReqHandled(res, resp);
}

exports.buy = function(req, res, resp) {
    var uid = req.uid;
    do {
        var id = req.args.id;
        var num = req.args.num;

        gCloudShop.updateShopList();

        var bought = gCloudShop.buy(uid, id, num, req.args.name, req.args.headpic);
        if( !bought ) {
            resp.data.update = 1;
        }else{
            resp.data.bought = bought;
        }
    }while(false);
    
    onReqHandled(res, resp);
}

exports.get_reward = function(req, res, resp) {
    var uid = req.uid;
    do {
        var awards = gCloudShop.getReward(req.uid, req.args.times, req.args.name);
        if( !awards ) {
            resp.code = 1; resp.desc = 'invalid'; break;
        }
        resp.data.awards = awards;
    }while(false);
    
    onReqHandled(res, resp);
}

exports.get_wins = function(req, res, resp) {
    var uid = req.uid;
    do {
        gCloudShop.updateShopList();

        resp.data.wins = gCloudShop.wins;
    }while(false);
    
    onReqHandled(res, resp);
}

exports.my_buy = function(req, res, resp) {
    var uid = req.uid;
    do {
        var reward = {};

        var boughTimes = req.args.bought;
        var wins = gCloudShop.wins;
        boughTimes.forEach(function(times){
            var win = wins[times];
            if( win && win.uid == uid ) {
                if( win.reward ) {
                    reward[times] = 2;
                }else{
                    reward[times] = 1;
                }
            }else{
                reward[times] = 0;
            }
        });

        resp.data.reward = reward;
    }while(false);
    
    onReqHandled(res, resp);
}

exports.CloudShop = CloudShop;
